package us.gaaoc.framework.webapp.backingbeans.admin;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import javax.faces.validator.ValidatorException;

import org.apache.log4j.Logger;
import org.hibernate.Hibernate;

import us.gaaoc.framework.model.Address;
import us.gaaoc.framework.model.AddressCategory;
import us.gaaoc.framework.model.AddressType;
import us.gaaoc.framework.model.CaseRecord;
import us.gaaoc.framework.model.OrgParticipants;
import us.gaaoc.framework.model.ParticipantRelationship;
import us.gaaoc.framework.model.Person;
import us.gaaoc.framework.model.PersonAddress;
import us.gaaoc.framework.model.PersonParticipants;
import us.gaaoc.framework.util.DateUtil;
import us.gaaoc.framework.webapp.backingbeans.BaseBackingBean;
import us.gaaoc.framework.webapp.util.Messages;

public class EditParticipants extends BaseBackingBean {
	/**
	 * properties
	 */
	private CaseRecord caseRecord;

	/**
	 * Data Models for the personParticipants
	 */
	private DataModel initiatingPartyPersonModel;

	private DataModel defendentPartyPersonModel;

	private DataModel witnessPersonModel;

	private DataModel initiatingPartyOrganizationDataModel;

	private Logger LOG = Logger.getLogger(EditParticipants.class);

	private FacesMessage message;

	private String courtUuid;

	private Person person;
	private Address address;

	private String firstName;
	private String middleName;
	private String lastName;
	private String suffixName;
	private Date dob;
	private String streetFullText;
	private String streetExtensionText;
	private String cityName;
	private String state;
	private String zipCode;

	private ArrayList<SelectItem> personTypes;
	private String selectedType;

	/**
	 * Constructor
	 * 
	 */
	public EditParticipants() {
		this.loadData();

		person = new Person();
		address = new Address();
		personTypes = new ArrayList<SelectItem>();

		List<ParticipantRelationship> l = this.getModelFacade()
				.getAllParticipantRelationshipCodes();

		for (ParticipantRelationship p : l) {
			if (p.getCode() != 2)
				personTypes.add(new SelectItem(String.valueOf(p.getCode()), p
						.getDescription()));
		}

		selectedType = personTypes.get(0).getLabel();
	}

	/**
	 * This method loads the data from the database for the particular filing.
	 * 
	 */
	@SuppressWarnings("unchecked")
	private void loadData() {
		Map sessionMap = this.getFacesContext().getExternalContext()
				.getSessionMap();

		courtUuid = (String) sessionMap.get("courtUuid");

		String caseUuid = (String) sessionMap.get("caseUuid");
		CaseRecord c = (CaseRecord) this.getModelFacade().findCaseRecordById(
				caseUuid, courtUuid);

		// Uncommented to fix issue:
		// b7006e6c-695c-11dd-945f-00301b45ff56
		Hibernate.initialize(c.getPersonParticipants());
		Hibernate.initialize(c.getOrgParticipants());
		Hibernate.initialize(c.getDocuments());
		// ---------------------

		List<PersonParticipants> pParticipantsList = c.getPersonParticipants();
		List<OrgParticipants> oParticipantsList = c.getOrgParticipants();

		List initiatingPartyOrganizationList = new ArrayList();

		// for initiating party person list
		List initiatingPartyPersonList = new ArrayList();

		// for defendant party person list
		List defendentPartyPersonList = new ArrayList();

		// for witness person list
		List witnessPersonList = new ArrayList();

		for (OrgParticipants o : oParticipantsList) {
			if (o.getRelationship().getCode() == 1)
				initiatingPartyOrganizationList.add(o);
		}

		for (PersonParticipants o : pParticipantsList) {
			if (o.getRelationship().getCode() == 1)
				initiatingPartyPersonList.add(o);
			else if (o.getRelationship().getCode() == 2)
				defendentPartyPersonList.add(o);
			else if (o.getRelationship().getCode() == 3)
				witnessPersonList.add(o);
		}

		initiatingPartyOrganizationDataModel = new ListDataModel();
		initiatingPartyOrganizationDataModel
				.setWrappedData(initiatingPartyOrganizationList);

		initiatingPartyPersonModel = new ListDataModel();
		initiatingPartyPersonModel.setWrappedData(initiatingPartyPersonList);

		defendentPartyPersonModel = new ListDataModel();
		defendentPartyPersonModel.setWrappedData(defendentPartyPersonList);

		witnessPersonModel = new ListDataModel();
		witnessPersonModel.setWrappedData(witnessPersonList);

		this.setCaseRecord(c);
	}

	public String save() {

		Person p = this.getModelFacade().findPersonByName(firstName,
				middleName, lastName);

		if (p == null) {

			person.setUuid(UUID.randomUUID().toString());
			person.setFirstName(firstName);
			person.setMiddleName(middleName);
			person.setLastName(lastName);
			person.setSuffixName(suffixName);
			address.setUuid(UUID.randomUUID().toString());
			address.setCityName(cityName);
			address.setState(state);
			address.setStreetExtensionText(streetExtensionText);
			address.setStreetFullText(streetFullText);
			address.setZipCode(zipCode);

			List<PersonAddress> list = new ArrayList<PersonAddress>();

			PersonAddress pa = new PersonAddress();
			AddressCategory aCategory = this.getModelFacade()
					.findAddressCateory(1);

			AddressType aType = this.getModelFacade().findAddressType(1,
					aCategory);

			pa.setAddress(address);
			pa.setPerson(person);
			pa.setAddressType(aType);
			pa.setUuid(UUID.randomUUID().toString());

			list.add(pa);

			person.setAddresses(list);

			PersonParticipants pp = new PersonParticipants();
			ParticipantRelationship relationship = this.getModelFacade()
					.findParticipantRelationship(Integer.valueOf(selectedType));
			pp.setCaseRecord(caseRecord);
			pp.setPerson(person);
			pp.setUuid(UUID.randomUUID().toString());
			pp.setRelationship(relationship);

			this.getModelFacade().insertPerson(person);
			this.getModelFacade().insertAddress(address);
			this.getModelFacade().insertPersonAddress(pa);
			this.getModelFacade().insertPersonParticipants(pp);
		} else {
			LOG.debug("in the else");
			AddressCategory aCategory = this.getModelFacade()
					.findAddressCateory(1);
			AddressType aType = this.getModelFacade().findAddressType(1,
					aCategory);
			Address a = this.getModelFacade().findAddress(p, aType);

			List<PersonAddress> list = new ArrayList<PersonAddress>();
			PersonAddress pa = new PersonAddress();

			if (a == null) {
				LOG.debug("address is null");
				address.setUuid(UUID.randomUUID().toString());
				address.setCityName(cityName);
				address.setState(state);
				address.setStreetExtensionText(streetExtensionText);
				address.setStreetFullText(streetFullText);
				address.setZipCode(zipCode);

				pa.setAddress(address);
				pa.setPerson(p);
				pa.setAddressType(aType);
				pa.setUuid(UUID.randomUUID().toString());

				this.getModelFacade().insertAddress(address);

			} else {
				pa.setAddress(a);
				pa.setPerson(p);
				pa.setAddressType(aType);
				pa.setUuid(UUID.randomUUID().toString());
			}

			this.getModelFacade().insertPersonAddress(pa);

			list.add(pa);

			p.setAddresses(list);

			PersonParticipants pp = new PersonParticipants();
			ParticipantRelationship relationship = this.getModelFacade()
					.findParticipantRelationship(Integer.valueOf(selectedType));
			pp.setCaseRecord(caseRecord);
			pp.setPerson(p);
			pp.setUuid(UUID.randomUUID().toString());
			pp.setRelationship(relationship);

			this.getModelFacade().insertPersonParticipants(pp);
		}

		firstName = "";
		middleName = "";
		lastName = "";
		suffixName = "";
		dob = new Date();
		streetFullText = "";
		streetExtensionText = "";
		cityName = "";
		state = "";
		zipCode = "";

		loadData();
		return null;
	}

	public void validateDate(FacesContext context, UIComponent component,
			Object value) throws ValidatorException, Exception {
		java.util.Date newValue = (java.util.Date) value;

		Calendar c = new GregorianCalendar();
		c.setTime(newValue);

		int date = c.get(Calendar.DATE);
		c.set(Calendar.DATE, date + 1);
		newValue = c.getTime();

		if (!isValidDate(newValue)) {
			message.setSeverity(FacesMessage.SEVERITY_ERROR);
			throw new ValidatorException(message);
		}
	}

	/**
	 * Method to check date to ensure that it is not a future date.
	 */
	protected boolean isValidDate(java.util.Date value) throws Exception {
		boolean validField = false;
		if (value.compareTo(DateUtil.getCurrentDate()) < 0) {
			validField = false;
			message = Messages.getMessage(
					"us.gaaoc.framework.webapp.util.errorMessage",
					"incorrectDate", null);
			message.setDetail(message.getDetail());
			message.setSeverity(FacesMessage.SEVERITY_ERROR);
		} else {
			validField = true;
		}
		return validField;
	}

	/**
	 * This method navigates user to the import filing page.
	 * 
	 * @return String
	 */
	public String gotoImportFiling() {
		return "gotoImportFiling";
	}

	/**
	 * This method navigates user to the reject filing page.
	 * 
	 * @return String
	 */
	public String gotoRejectFiling() {
		return "gotoRejectFiling";
	}

	/**
	 * This method navigates user to the previous page.
	 * 
	 * @return
	 */
	public String back() {
		Map sessionMap = this.getFacesContext().getExternalContext()
				.getSessionMap();
		sessionMap.remove("from");

		return "childEnforcementCaseDetailsPage";
	}

	/**
	 * @param initiatingPartyOrganizationDataModel
	 *            The initiatingPartyOrganizationDataModel to set.
	 */
	public void setInitiatingPartyOrganizationDataModel(
			DataModel initiatingPartyOrganizationDataModel) {
		this.initiatingPartyOrganizationDataModel = initiatingPartyOrganizationDataModel;
	}

	/**
	 * @return Returns the caseRecord.
	 */
	public CaseRecord getCaseRecord() {
		return caseRecord;
	}

	/**
	 * Setter for property caseRecord
	 * 
	 * @param caseRecord
	 */
	public void setCaseRecord(CaseRecord caseRecord) {
		this.caseRecord = caseRecord;
	}

	/**
	 * Getter for property defendentPartyPersonModel
	 * 
	 * @return defendentPartyPersonModel
	 */
	public DataModel getDefendentPartyPersonModel() {
		return defendentPartyPersonModel;
	}

	/**
	 * Setter for property defendentPartyPersonModel
	 * 
	 * @param defendentPartyPersonModel
	 */
	public void setDefendentPartyPersonModel(DataModel defendentPartyPersonModel) {
		this.defendentPartyPersonModel = defendentPartyPersonModel;
	}

	/**
	 * Getter for property initiationgPartyPersonModel
	 * 
	 * @return initiatingPartyPersonModel
	 */
	public DataModel getInitiatingPartyPersonModel() {
		return initiatingPartyPersonModel;
	}

	/**
	 * Setter for property initiatingPartyPersonmodel
	 * 
	 * @param initiatingPartyPersonModel
	 */
	public void setInitiatingPartyPersonModel(
			DataModel initiatingPartyPersonModel) {
		this.initiatingPartyPersonModel = initiatingPartyPersonModel;
	}

	/**
	 * Getter for property initiatingPartyOrganizationDataModel
	 * 
	 * @return initiatingPartyOrganizationDataModel
	 */
	public DataModel getInitiatingPartyOrganizationDataModel() {
		return initiatingPartyOrganizationDataModel;
	}

	/**
	 * Getter for property witnessPersonModel
	 * 
	 * @return
	 */
	public DataModel getWitnessPersonModel() {
		return witnessPersonModel;
	}

	/**
	 * Setter for property witnessPersonModel
	 * 
	 * @param witnessPersonModel
	 */
	public void setWitnessPersonModel(DataModel witnessPersonModel) {
		this.witnessPersonModel = witnessPersonModel;
	}

	public FacesMessage getMessage() {
		return message;
	}

	public void setMessage(FacesMessage message) {
		this.message = message;
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getMiddleName() {
		return middleName;
	}

	public void setMiddleName(String middleName) {
		this.middleName = middleName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getSuffixName() {
		return suffixName;
	}

	public void setSuffixName(String suffixName) {
		this.suffixName = suffixName;
	}

	public Date getDob() {
		return dob;
	}

	public void setDob(Date dob) {
		this.dob = dob;
	}

	public String getStreetFullText() {
		return streetFullText;
	}

	public void setStreetFullText(String streetFullText) {
		this.streetFullText = streetFullText;
	}

	public String getStreetExtensionText() {
		return streetExtensionText;
	}

	public void setStreetExtensionText(String streetExtensionText) {
		this.streetExtensionText = streetExtensionText;
	}

	public String getCityName() {
		return cityName;
	}

	public void setCityName(String cityName) {
		this.cityName = cityName;
	}

	public String getState() {
		return state;
	}

	public void setState(String state) {
		this.state = state;
	}

	public String getZipCode() {
		return zipCode;
	}

	public void setZipCode(String zipCode) {
		this.zipCode = zipCode;
	}

	public void setPersonTypes(ArrayList<SelectItem> personTypes) {
		this.personTypes = personTypes;
	}

	public List<SelectItem> getPersonTypes() {
		return personTypes;
	}

	public void setSelectedType(String selectedType) {
		this.selectedType = selectedType;
	}

	public String getSelectedType() {
		return selectedType;
	}
}